/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package da;

import da.exceptions.IllegalOrphanException;
import da.exceptions.NonexistentEntityException;
import da.exceptions.PreexistingEntityException;
import da.exceptions.RollbackFailureException;
import entities.Account;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import entities.Role;
import entities.Department;
import entities.Relation;
import java.util.ArrayList;
import java.util.List;
import entities.Complain;
import entities.Reply;
import entities.News;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.transaction.UserTransaction;

/**
 *
 * @author THOHCGC00177
 */
public class AccountJpaController implements Serializable {

    public AccountJpaController(UserTransaction utx, EntityManagerFactory emf) {
        this.utx = utx;
        this.emf = emf;
    }
    private UserTransaction utx = null;
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Account account) throws PreexistingEntityException, RollbackFailureException, Exception {
        if (account.getRelationList() == null) {
            account.setRelationList(new ArrayList<Relation>());
        }
        if (account.getComplainList() == null) {
            account.setComplainList(new ArrayList<Complain>());
        }
        if (account.getReplyList() == null) {
            account.setReplyList(new ArrayList<Reply>());
        }
        if (account.getNewsList() == null) {
            account.setNewsList(new ArrayList<News>());
        }
        EntityManager em = null;
        try {
            utx.begin();
            em = getEntityManager();
            Role roleId = account.getRoleId();
            if (roleId != null) {
                roleId = em.getReference(roleId.getClass(), roleId.getId());
                account.setRoleId(roleId);
            }
            Department departmentId = account.getDepartmentId();
            if (departmentId != null) {
                departmentId = em.getReference(departmentId.getClass(), departmentId.getId());
                account.setDepartmentId(departmentId);
            }
            List<Relation> attachedRelationList = new ArrayList<Relation>();
            for (Relation relationListRelationToAttach : account.getRelationList()) {
                relationListRelationToAttach = em.getReference(relationListRelationToAttach.getClass(), relationListRelationToAttach.getId());
                attachedRelationList.add(relationListRelationToAttach);
            }
            account.setRelationList(attachedRelationList);
            List<Complain> attachedComplainList = new ArrayList<Complain>();
            for (Complain complainListComplainToAttach : account.getComplainList()) {
                complainListComplainToAttach = em.getReference(complainListComplainToAttach.getClass(), complainListComplainToAttach.getId());
                attachedComplainList.add(complainListComplainToAttach);
            }
            account.setComplainList(attachedComplainList);
            List<Reply> attachedReplyList = new ArrayList<Reply>();
            for (Reply replyListReplyToAttach : account.getReplyList()) {
                replyListReplyToAttach = em.getReference(replyListReplyToAttach.getClass(), replyListReplyToAttach.getId());
                attachedReplyList.add(replyListReplyToAttach);
            }
            account.setReplyList(attachedReplyList);
            List<News> attachedNewsList = new ArrayList<News>();
            for (News newsListNewsToAttach : account.getNewsList()) {
                newsListNewsToAttach = em.getReference(newsListNewsToAttach.getClass(), newsListNewsToAttach.getId());
                attachedNewsList.add(newsListNewsToAttach);
            }
            account.setNewsList(attachedNewsList);
            em.persist(account);
            if (roleId != null) {
                roleId.getAccountList().add(account);
                roleId = em.merge(roleId);
            }
            if (departmentId != null) {
                departmentId.getAccountList().add(account);
                departmentId = em.merge(departmentId);
            }
            for (Relation relationListRelation : account.getRelationList()) {
                Account oldTechnicalIdOfRelationListRelation = relationListRelation.getTechnicalId();
                relationListRelation.setTechnicalId(account);
                relationListRelation = em.merge(relationListRelation);
                if (oldTechnicalIdOfRelationListRelation != null) {
                    oldTechnicalIdOfRelationListRelation.getRelationList().remove(relationListRelation);
                    oldTechnicalIdOfRelationListRelation = em.merge(oldTechnicalIdOfRelationListRelation);
                }
            }
            for (Complain complainListComplain : account.getComplainList()) {
                Account oldAccountIdOfComplainListComplain = complainListComplain.getAccountId();
                complainListComplain.setAccountId(account);
                complainListComplain = em.merge(complainListComplain);
                if (oldAccountIdOfComplainListComplain != null) {
                    oldAccountIdOfComplainListComplain.getComplainList().remove(complainListComplain);
                    oldAccountIdOfComplainListComplain = em.merge(oldAccountIdOfComplainListComplain);
                }
            }
            for (Reply replyListReply : account.getReplyList()) {
                Account oldTechnicalIdOfReplyListReply = replyListReply.getTechnicalId();
                replyListReply.setTechnicalId(account);
                replyListReply = em.merge(replyListReply);
                if (oldTechnicalIdOfReplyListReply != null) {
                    oldTechnicalIdOfReplyListReply.getReplyList().remove(replyListReply);
                    oldTechnicalIdOfReplyListReply = em.merge(oldTechnicalIdOfReplyListReply);
                }
            }
            for (News newsListNews : account.getNewsList()) {
                Account oldAcountIdOfNewsListNews = newsListNews.getAcountId();
                newsListNews.setAcountId(account);
                newsListNews = em.merge(newsListNews);
                if (oldAcountIdOfNewsListNews != null) {
                    oldAcountIdOfNewsListNews.getNewsList().remove(newsListNews);
                    oldAcountIdOfNewsListNews = em.merge(oldAcountIdOfNewsListNews);
                }
            }
            utx.commit();
        } catch (Exception ex) {
            try {
                utx.rollback();
            } catch (Exception re) {
                throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
            }
            if (findAccount(account.getId()) != null) {
                throw new PreexistingEntityException("Account " + account + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Account account) throws IllegalOrphanException, NonexistentEntityException, RollbackFailureException, Exception {
        EntityManager em = null;
        try {
            utx.begin();
            em = getEntityManager();
            Account persistentAccount = em.find(Account.class, account.getId());
            Role roleIdOld = persistentAccount.getRoleId();
            Role roleIdNew = account.getRoleId();
            Department departmentIdOld = persistentAccount.getDepartmentId();
            Department departmentIdNew = account.getDepartmentId();
            List<Relation> relationListOld = persistentAccount.getRelationList();
            List<Relation> relationListNew = account.getRelationList();
            List<Complain> complainListOld = persistentAccount.getComplainList();
            List<Complain> complainListNew = account.getComplainList();
            List<Reply> replyListOld = persistentAccount.getReplyList();
            List<Reply> replyListNew = account.getReplyList();
            List<News> newsListOld = persistentAccount.getNewsList();
            List<News> newsListNew = account.getNewsList();
            List<String> illegalOrphanMessages = null;
            for (Relation relationListOldRelation : relationListOld) {
                if (!relationListNew.contains(relationListOldRelation)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Relation " + relationListOldRelation + " since its technicalId field is not nullable.");
                }
            }
            for (Complain complainListOldComplain : complainListOld) {
                if (!complainListNew.contains(complainListOldComplain)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Complain " + complainListOldComplain + " since its accountId field is not nullable.");
                }
            }
            for (Reply replyListOldReply : replyListOld) {
                if (!replyListNew.contains(replyListOldReply)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Reply " + replyListOldReply + " since its technicalId field is not nullable.");
                }
            }
            for (News newsListOldNews : newsListOld) {
                if (!newsListNew.contains(newsListOldNews)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain News " + newsListOldNews + " since its acountId field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (roleIdNew != null) {
                roleIdNew = em.getReference(roleIdNew.getClass(), roleIdNew.getId());
                account.setRoleId(roleIdNew);
            }
            if (departmentIdNew != null) {
                departmentIdNew = em.getReference(departmentIdNew.getClass(), departmentIdNew.getId());
                account.setDepartmentId(departmentIdNew);
            }
            List<Relation> attachedRelationListNew = new ArrayList<Relation>();
            for (Relation relationListNewRelationToAttach : relationListNew) {
                relationListNewRelationToAttach = em.getReference(relationListNewRelationToAttach.getClass(), relationListNewRelationToAttach.getId());
                attachedRelationListNew.add(relationListNewRelationToAttach);
            }
            relationListNew = attachedRelationListNew;
            account.setRelationList(relationListNew);
            List<Complain> attachedComplainListNew = new ArrayList<Complain>();
            for (Complain complainListNewComplainToAttach : complainListNew) {
                complainListNewComplainToAttach = em.getReference(complainListNewComplainToAttach.getClass(), complainListNewComplainToAttach.getId());
                attachedComplainListNew.add(complainListNewComplainToAttach);
            }
            complainListNew = attachedComplainListNew;
            account.setComplainList(complainListNew);
            List<Reply> attachedReplyListNew = new ArrayList<Reply>();
            for (Reply replyListNewReplyToAttach : replyListNew) {
                replyListNewReplyToAttach = em.getReference(replyListNewReplyToAttach.getClass(), replyListNewReplyToAttach.getId());
                attachedReplyListNew.add(replyListNewReplyToAttach);
            }
            replyListNew = attachedReplyListNew;
            account.setReplyList(replyListNew);
            List<News> attachedNewsListNew = new ArrayList<News>();
            for (News newsListNewNewsToAttach : newsListNew) {
                newsListNewNewsToAttach = em.getReference(newsListNewNewsToAttach.getClass(), newsListNewNewsToAttach.getId());
                attachedNewsListNew.add(newsListNewNewsToAttach);
            }
            newsListNew = attachedNewsListNew;
            account.setNewsList(newsListNew);
            account = em.merge(account);
            if (roleIdOld != null && !roleIdOld.equals(roleIdNew)) {
                roleIdOld.getAccountList().remove(account);
                roleIdOld = em.merge(roleIdOld);
            }
            if (roleIdNew != null && !roleIdNew.equals(roleIdOld)) {
                roleIdNew.getAccountList().add(account);
                roleIdNew = em.merge(roleIdNew);
            }
            if (departmentIdOld != null && !departmentIdOld.equals(departmentIdNew)) {
                departmentIdOld.getAccountList().remove(account);
                departmentIdOld = em.merge(departmentIdOld);
            }
            if (departmentIdNew != null && !departmentIdNew.equals(departmentIdOld)) {
                departmentIdNew.getAccountList().add(account);
                departmentIdNew = em.merge(departmentIdNew);
            }
            for (Relation relationListNewRelation : relationListNew) {
                if (!relationListOld.contains(relationListNewRelation)) {
                    Account oldTechnicalIdOfRelationListNewRelation = relationListNewRelation.getTechnicalId();
                    relationListNewRelation.setTechnicalId(account);
                    relationListNewRelation = em.merge(relationListNewRelation);
                    if (oldTechnicalIdOfRelationListNewRelation != null && !oldTechnicalIdOfRelationListNewRelation.equals(account)) {
                        oldTechnicalIdOfRelationListNewRelation.getRelationList().remove(relationListNewRelation);
                        oldTechnicalIdOfRelationListNewRelation = em.merge(oldTechnicalIdOfRelationListNewRelation);
                    }
                }
            }
            for (Complain complainListNewComplain : complainListNew) {
                if (!complainListOld.contains(complainListNewComplain)) {
                    Account oldAccountIdOfComplainListNewComplain = complainListNewComplain.getAccountId();
                    complainListNewComplain.setAccountId(account);
                    complainListNewComplain = em.merge(complainListNewComplain);
                    if (oldAccountIdOfComplainListNewComplain != null && !oldAccountIdOfComplainListNewComplain.equals(account)) {
                        oldAccountIdOfComplainListNewComplain.getComplainList().remove(complainListNewComplain);
                        oldAccountIdOfComplainListNewComplain = em.merge(oldAccountIdOfComplainListNewComplain);
                    }
                }
            }
            for (Reply replyListNewReply : replyListNew) {
                if (!replyListOld.contains(replyListNewReply)) {
                    Account oldTechnicalIdOfReplyListNewReply = replyListNewReply.getTechnicalId();
                    replyListNewReply.setTechnicalId(account);
                    replyListNewReply = em.merge(replyListNewReply);
                    if (oldTechnicalIdOfReplyListNewReply != null && !oldTechnicalIdOfReplyListNewReply.equals(account)) {
                        oldTechnicalIdOfReplyListNewReply.getReplyList().remove(replyListNewReply);
                        oldTechnicalIdOfReplyListNewReply = em.merge(oldTechnicalIdOfReplyListNewReply);
                    }
                }
            }
            for (News newsListNewNews : newsListNew) {
                if (!newsListOld.contains(newsListNewNews)) {
                    Account oldAcountIdOfNewsListNewNews = newsListNewNews.getAcountId();
                    newsListNewNews.setAcountId(account);
                    newsListNewNews = em.merge(newsListNewNews);
                    if (oldAcountIdOfNewsListNewNews != null && !oldAcountIdOfNewsListNewNews.equals(account)) {
                        oldAcountIdOfNewsListNewNews.getNewsList().remove(newsListNewNews);
                        oldAcountIdOfNewsListNewNews = em.merge(oldAcountIdOfNewsListNewNews);
                    }
                }
            }
            utx.commit();
        } catch (Exception ex) {
            try {
                utx.rollback();
            } catch (Exception re) {
                throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
            }
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = account.getId();
                if (findAccount(id) == null) {
                    throw new NonexistentEntityException("The account with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws IllegalOrphanException, NonexistentEntityException, RollbackFailureException, Exception {
        EntityManager em = null;
        try {
            utx.begin();
            em = getEntityManager();
            Account account;
            try {
                account = em.getReference(Account.class, id);
                account.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The account with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            List<Relation> relationListOrphanCheck = account.getRelationList();
            for (Relation relationListOrphanCheckRelation : relationListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Account (" + account + ") cannot be destroyed since the Relation " + relationListOrphanCheckRelation + " in its relationList field has a non-nullable technicalId field.");
            }
            List<Complain> complainListOrphanCheck = account.getComplainList();
            for (Complain complainListOrphanCheckComplain : complainListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Account (" + account + ") cannot be destroyed since the Complain " + complainListOrphanCheckComplain + " in its complainList field has a non-nullable accountId field.");
            }
            List<Reply> replyListOrphanCheck = account.getReplyList();
            for (Reply replyListOrphanCheckReply : replyListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Account (" + account + ") cannot be destroyed since the Reply " + replyListOrphanCheckReply + " in its replyList field has a non-nullable technicalId field.");
            }
            List<News> newsListOrphanCheck = account.getNewsList();
            for (News newsListOrphanCheckNews : newsListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Account (" + account + ") cannot be destroyed since the News " + newsListOrphanCheckNews + " in its newsList field has a non-nullable acountId field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Role roleId = account.getRoleId();
            if (roleId != null) {
                roleId.getAccountList().remove(account);
                roleId = em.merge(roleId);
            }
            Department departmentId = account.getDepartmentId();
            if (departmentId != null) {
                departmentId.getAccountList().remove(account);
                departmentId = em.merge(departmentId);
            }
            em.remove(account);
            utx.commit();
        } catch (Exception ex) {
            try {
                utx.rollback();
            } catch (Exception re) {
                throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Account> findAccountEntities() {
        return findAccountEntities(true, -1, -1);
    }

    public List<Account> findAccountEntities(int maxResults, int firstResult) {
        return findAccountEntities(false, maxResults, firstResult);
    }

    private List<Account> findAccountEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Account.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Account findAccount(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Account.class, id);
        } finally {
            em.close();
        }
    }

    public int getAccountCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Account> rt = cq.from(Account.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
